#include "NetBase.h"

#include "SelectPoll.h"
#include "EpollPoll.h"

#ifdef _WIN32
#include <WS2tcpip.h>
#else
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#endif

CNetBase::CNetBase()
    :m_pPoll(NULL)
{
}


CNetBase::~CNetBase()
{
    if (m_pPoll != NULL)
    {
        delete m_pPoll;
        m_pPoll = NULL;
    }
}

bool CNetBase::Init()
{
    if (m_pPoll != NULL)
    {
        delete m_pPoll;
    }

    m_pPoll = new CSelectPoll();
    if (m_pPoll == NULL)
    {
        return false;
    }

    if (!m_pPoll->Init(1024))
    {
        printf("ERROR Init|Poll init fail\n");
        return false;
    }

    return true;
}

int CNetBase::AddListen(const char *pIp, int iPort)
{
    if (m_pPoll == NULL)
    {
        return -1;
    }

    int iListenSocket = (int)socket(AF_INET, SOCK_STREAM, 0);

    if (iListenSocket == -1)
    {
        printf("ERROR AddListen|create socket -1\n");
        return -1;
    }

    //设置端口复用
    int iReuseaddr = true;
    if (0 != setsockopt(iListenSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&iReuseaddr, sizeof(iReuseaddr)))
    {
        printf("ERROR AddListen|setsockopt not 0. socket:%d\n", iListenSocket);
        return -1;
    }

    //绑定地址
    struct sockaddr_in stSockAddrIn;
    stSockAddrIn.sin_family = AF_INET;
    if (NULL == pIp)
    {
#ifdef _WIN32
        stSockAddrIn.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
#else
        stSockAddrIn.sin_addr.s_addr = htonl(INADDR_ANY);
#endif
    }
    else
    {
        if (inet_pton(AF_INET, pIp, (void*)&(stSockAddrIn.sin_addr)) <= 0)
        {
            printf("ERROR AddListen|inet_pton less 0.ip:%s\n", pIp);
            return -1;
        }
    }
    stSockAddrIn.sin_port = htons(iPort);

    if (0 != bind(iListenSocket, (struct sockaddr *)&stSockAddrIn, sizeof(struct sockaddr)))
    {
        printf("ERROR AddListen|bind not 0.socket:%d\n", iListenSocket);
        return -1;
    }

    if (0 != listen(iListenSocket, 511))
    {
        printf("ERROR AddListen|listen not 0.socket:%d\n", iListenSocket);
        return -1;
    }

    SSocketData *pSocketData = CreateSocketData(iListenSocket, ENM_SOCKET_EVENT_TYPE_ACCEPT);
    if (pSocketData == NULL)
    {
        printf("ERROR AddListen|CreateSocketData is NULL\n");
        return -1;
    }
    if (!m_mapSocketMap.insert(pair<int, SSocketData*>(iListenSocket, pSocketData)).second)
    {
        printf("ERROR AddListen|SocketMap insert fail.socket:%d\n", iListenSocket);
        return -1;
    }

    if (!m_pPoll->AddReadSocket(iListenSocket))
    {
        printf("ERROR AddListen|AddReadSocket fail.socket:%d\n", iListenSocket);
        m_mapSocketMap.erase(iListenSocket);
        delete pSocketData;
        pSocketData = NULL;
        return -1;
    }

    return iListenSocket;
}

int CNetBase::AddConnect(const char *pIp, int iPort)
{
    if (m_pPoll == NULL)
    {
        printf("ERROR AddConnect|Poll is NULL.ip:%s port:%d\n", pIp, iPort);
        return -1;
    }

    if (pIp == NULL || iPort <= 0)
    {
        printf("ERROR AddConnect|IP is NULL or Port less 0.port:%d\n", iPort);
        return -1;
    }

    int iConnectSocket = (int)socket(AF_INET, SOCK_STREAM, 0);

    if (iConnectSocket == -1)
    {
        printf("ERROR AddConnect|create socket -1\n");
        return -1;
    }

    //设置端口复用
    int iReuseaddr = true;
    if (0 != setsockopt(iConnectSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&iReuseaddr, sizeof(iReuseaddr)))
    {
        printf("ERROR AddConnect|setsockopt is not 0. socket:%d\n", iConnectSocket);
        return -1;
    }

    //设置非阻塞
#ifdef _WIN32
    u_long lArgp = 1;
    if (ioctlsocket(iConnectSocket, FIONBIO, &lArgp) < 0)
    {
        printf("ERROR AddListen|ioctlsocket is less 0. socket:%d\n", iConnectSocket);
        return -1;
    }
#else 
    int iFlags = fcntl(iConnectSocket, F_GETFL);
    if (iFlags == -1)
    {
        printf("ERROR AddListen|fcntl F_GETFL is -1. socket:%d\n", iConnectSocket);
        return -1;
    }
    if (fcntl(iConnectSocket, F_SETFL, iFlags | O_NONBLOCK) == -1)
    {
        printf("ERROR AddListen|fcntl F_SETFL is -1. socket:%d\n", iConnectSocket);
        return -1;
    }
#endif

    //绑定地址
    struct sockaddr_in stSockAddrIn;
    stSockAddrIn.sin_family = AF_INET;
    if (inet_pton(AF_INET, pIp, (void*)&(stSockAddrIn.sin_addr)) <= 0)
    {
        printf("ERROR AddListen|inet_pton less 0. ip:%s\n", pIp);
        return -1;
    }

    stSockAddrIn.sin_port = htons(iPort);
    int iRet = connect(iConnectSocket, (struct  sockaddr*)&stSockAddrIn, sizeof(struct sockaddr));

    if (iRet == -1)
    {
#ifdef _WIN32
        iRet = WSAGetLastError();
        if (iRet != WSAEWOULDBLOCK)
        {
            printf("ERROR AddListen|connect fail.error:%d\n", iRet);
            return -1;
        }
#else
        iRet = errno;
        if (iRet != EINPROGRESS)
        {
            printf("ERROR AddListen|connect fail.error:%d\n", iRet);
            return -1;
        }
#endif
    }

    SSocketData *pSocketData = CreateSocketData(iConnectSocket, ENM_SOCKET_EVENT_TYPE_CONNECT);

    if (pSocketData == NULL)
    {
        printf("ERROR AddListen|SocketData is NULL.\n");
        return -1;
    }

    if (!m_mapSocketMap.insert(pair<int, SSocketData*>(iConnectSocket, pSocketData)).second)
    {
        printf("ERROR AddListen|SocketMap insert fail.socket:%d\n", iConnectSocket);
        return -1;
    }

    if (!m_pPoll->AddWriteSocket(iConnectSocket))
    {
        m_mapSocketMap.erase(iConnectSocket);
        delete pSocketData;
        pSocketData = NULL;
        printf("ERROR AddListen|AddWriteSocket fail. socket:%d\n", iConnectSocket);
        return -1;
    }
    return iConnectSocket;
}

int CNetBase::Polling(int iWaitTime)
{
    if (m_pPoll == NULL)
    {
        printf("ERROR Polling|Poll is NULL.\n");
        return 0;
    }

    int iCount = m_pPoll->Polling(iWaitTime);

    if (iCount <= 0)
    {
        return 0;
    }

    static char cBuff[1024 * 64] = { 0 };

    while (iCount--)
    {
        const SReadySocket * pReady = m_pPoll->GetReadySocket();
        m_pPoll->PopReadySocket();

        if (pReady == NULL)
        {
            printf("ERROR Polling|ReadySocket is NULL\n");
            break;
        }

        SocketMap::iterator mapIt = m_mapSocketMap.find(pReady->iSocket);

        if (mapIt == m_mapSocketMap.end() || mapIt->second == NULL)
        {
            printf("ERROR Polling|MapIt is end or MapIt->second is NULL. socket:%d\n", pReady->iSocket);
            continue;
        }

        SSocketData &stSocketData = *(mapIt->second);

        if (pReady->eType & ENM_SOCKET_READY_EVENT_TYPE_READ)
        {
            if (stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_ACCEPT)
            {
                struct sockaddr_in stSockAddrIn;
                int iSockeAddrInLen = sizeof(stSockAddrIn);
                int iClientSocket = (int)accept(stSocketData.iSocket, (struct sockaddr *)&stSockAddrIn, (socklen_t*)&iSockeAddrInLen);

                if (iClientSocket == -1)
                {
                    printf("ERROR Polling|accept fail. socket:%d\n", stSocketData.iSocket);
                    continue;
                }

                m_pPoll->AddReadSocket(stSocketData.iSocket);
                OnAccept(stSocketData.iSocket, iClientSocket);
            }
            else if (stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_READ)
            {
                int iCount = 0;
                if (stSocketData.iBufferUse < MAX_DATA_SIZE)
                {
                    iCount += recv(stSocketData.iSocket, stSocketData.csDataBuffer + stSocketData.iBufferUse,
                        sizeof(stSocketData.csDataBuffer) - stSocketData.iBufferUse, 0);
                }
                m_pPoll->AddReadSocket(stSocketData.iSocket);

                if (iCount <= 0)
                {
                    OnClose(stSocketData.iSocket);
                }
                else
                {
                    stSocketData.iBufferUse += iCount;
                    int iLeft = OnRecv(stSocketData.iSocket, stSocketData.csDataBuffer, stSocketData.iBufferUse);

                    if (iLeft != 0)
                    {
                        memcpy(stSocketData.csDataBuffer, stSocketData.csDataBuffer + stSocketData.iBufferUse - iLeft, iLeft);
                        //printf("DEBUG Left:%d\n", iLeft);
                    }
                    stSocketData.iBufferUse = iLeft;
                }
            }
        }
        else if (pReady->eType & ENM_SOCKET_READY_EVENT_TYPE_WRITE)
        {
            if (stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_CONNECT)
            {
                if (OnConnect(stSocketData.iSocket))
                {
                    stSocketData.iEventType &= ~ENM_SOCKET_EVENT_TYPE_CONNECT;

                    if ((stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_WRITE_MASK) == 0)
                    {
                        m_pPoll->RemoveWriteSocket(stSocketData.iSocket);
                    }

                    SSocketData *pRead = mapIt->second;
                    if (pRead != NULL)
                    {
                        pRead->iEventType |= ENM_SOCKET_EVENT_TYPE_READ;
                        m_pPoll->AddReadSocket(pRead->iSocket);
                    }
                }
            }
            else if (stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_WRITE)
            {
                stSocketData.iEventType &= ~ENM_SOCKET_EVENT_TYPE_WRITE;

                if ((stSocketData.iEventType & ENM_SOCKET_EVENT_TYPE_WRITE_MASK) == 0)
                {
                    m_pPoll->RemoveWriteSocket(stSocketData.iSocket);
                }

                int iSendSize = Send(stSocketData.iSocket, NULL, 0);

                if( iSendSize <= 0)
                {
                    Close(stSocketData.iSocket);
                }
            }
        }
    }

    return 0;
}

int CNetBase::OnRecv(const int iSocket, char *pData, int iLen)
{
    if (pData == NULL || iLen < 0 || iSocket < 0)
    {
        printf("ERROR OnRecv|Data is NULL or Len less 0 or Socket less 0.Len:%d Socket:%d\n", iLen, iSocket);
        return 0;
    }

    //printf("DEBUG OnRecv.Len:%d Socket:%d\n", iLen, iSocket);

    SocketMap::iterator itMap = m_mapSocketMap.find(iSocket);

    if (m_mapSocketMap.end() == itMap)
    {
        printf("ERROR OnRecv|SocketMap is end. Socket:%d\n", iSocket);
        return 0;
    }

    SSocketData *pSocketData = itMap->second;
    if (NULL == pSocketData)
    {
        printf("ERROR OnRecv|ItMap->second is NULL. Socket:%d\n", iSocket);
        return 0;
    }

    //获取空闲空间
    SBufferNode *pCurBufferNode = NULL;
    int iOffset = 0;

    if (pSocketData->pRecvHeadNode != NULL)
    {
        //接收之前未接收完整的报文
        pCurBufferNode = SBufferNode::GetPrevNode(pSocketData->pRecvHeadNode);

        if (pCurBufferNode == NULL)
        {
            printf("ERROR OnRecv|CurBufferNode is NULL.\n");
            return 0;
        }

        int iLastNeedSize = pCurBufferNode->iTotal - pCurBufferNode->iDealed;

        if (iLastNeedSize > 0)
        {
            //printf("DEBUG LastNeed.Need:%d Len:%d Total:%d Deal:%d Socket:%d\n",
            //    iLastNeedSize, iLen, pCurBufferNode->iTotal, pCurBufferNode->iDealed, pSocketData->iSocket);
            if (iLastNeedSize >= iLen)
            {
                memcpy((char*)&pCurBufferNode->stNetPacket + pCurBufferNode->iDealed, pData, iLen);
                pCurBufferNode->iDealed += iLen;
                iLen = 0;
            }
            else
            {
                memcpy((char*)&pCurBufferNode->stNetPacket + pCurBufferNode->iDealed, pData, iLastNeedSize);
                iLen -= iLastNeedSize;
                pCurBufferNode->iDealed += iLastNeedSize;
                iOffset = iLastNeedSize;
            }
        }
    }

    //保存报文
    while (iLen > 0)
    {
        //剩下报文如果不足报文头
        if (iLen <= (sizeof(SNetPacket) - DATA_SIZE))
        {
            //printf("DEBUG Not recv all.Len:%d Socket:%d\n ", iLen, pSocketData->iSocket);
            return iLen;
        }

        //创建新节点接收报文
        SNetPacket *pNewPacket = (SNetPacket *)(pData + iOffset);
        if (pNewPacket == NULL)
        {
            printf("ERROR OnRecv|NewPacket is NULL.Offset:%d\n", iOffset);
            return 0;
        }
        if (pNewPacket->uCheckValue != CHECK_VALUE)
        {
            printf("ERROR OnRecv|CheckValue is error. CheckValue:%d, Socket:%d Flag:%d Len:%d Data:%s\n",
                pNewPacket->uCheckValue, iSocket, pNewPacket->uFlag, pNewPacket->uLength, pNewPacket->csData);
            return 0;
        }

        pCurBufferNode = (SBufferNode *)GetFreeData(pNewPacket->uLength + sizeof(SBufferNode) - sizeof(SNetPacket));
        if (pCurBufferNode == NULL)
        {
            printf("ERROR OnRecv|GetFreeData is NULL. Size:%d\n",(int)(pNewPacket->uLength + sizeof(SBufferNode) - sizeof(SNetPacket)));
            return 0;
        }
        pCurBufferNode->iTotal = pNewPacket->uLength;
        pCurBufferNode->iDealed = 0;


        //printf("DEBUG NewPacket.Len:%d Total:%d Deal:%d Socket:%d\n",
        //    iLen, pCurBufferNode->iTotal, pCurBufferNode->iDealed, pSocketData->iSocket);

        if (!SBufferNode::AddNode(pSocketData->pRecvHeadNode, pCurBufferNode))
        {
            printf("ERROR OnRecv|AddNode is Fail.\n");
            return 0;
        }
        //接收数据
        if (iLen < pCurBufferNode->iTotal)
        {
            //printf("DEBUG Not recv all.Len:%d Total:%d Deal:%d Socket:%d\n",
            //    iLen, pCurBufferNode->iTotal, pCurBufferNode->iDealed, pSocketData->iSocket);
            memcpy(&(pCurBufferNode->stNetPacket), pData + iOffset, iLen);
            pCurBufferNode->iDealed += iLen;
            iLen = 0;
        }
        else
        {
            memcpy(&(pCurBufferNode->stNetPacket), pData + iOffset, pCurBufferNode->iTotal);
            pCurBufferNode->iDealed = pCurBufferNode->iTotal;
            iLen -= pCurBufferNode->iTotal;
            iOffset += pCurBufferNode->iTotal;
        }
    }

    //处理并删除报文
    while (pSocketData->pRecvHeadNode != NULL)
    {
        if (pSocketData->pRecvHeadNode->iDealed < pSocketData->pRecvHeadNode->iTotal)
        {
            break;
        }
        SNetPacket &stNetPacket = pSocketData->pRecvHeadNode->stNetPacket;
        int iPacketSize = stNetPacket.uLength - sizeof(SNetPacket) + DATA_SIZE;
        bool bIsOk = OnPacket(iSocket, stNetPacket.csData, iPacketSize);
        if (!bIsOk)
        {
            break;
        }

        SBufferNode *pFree = pSocketData->pRecvHeadNode;
        pSocketData->pRecvHeadNode = SBufferNode::RemoveNode(pSocketData->pRecvHeadNode);
        ReleaseData((char*)pFree);
    }

    return 0;
}

bool CNetBase::OnPacket(const int iSocket, char *pData, int iLen)
{
    return true;
}

bool CNetBase::OnAccept(const int iListenSocket, const int iClientSocket)
{
    SSocketData *pSocket = CreateSocketData(iClientSocket, ENM_SOCKET_EVENT_TYPE_READ);
    if (pSocket == NULL)
    {
        printf("ERROR OnAccept|SSocketData is NULL. socket:%d\n", iClientSocket);
        return false;
    }

    if (!m_mapSocketMap.insert(pair<int, SSocketData*>(iClientSocket, pSocket)).second)
    {
        printf("ERROR OnAccept|SocketMap insert fail. socket:%d\n", iClientSocket);
        return false;
    }

    if (!m_pPoll->AddReadSocket(iClientSocket))
    {
        m_mapSocketMap.erase(iClientSocket);
        delete pSocket;
        pSocket = NULL;

        printf("ERROR OnAccept|AddReadSocket fail. socket:%d\n", iClientSocket);
        return false;
    }
    return true;
}

bool CNetBase::OnConnect(const int iSocket)
{
    return true;
}

bool CNetBase::OnClose(const int iSocket)
{
    m_pPoll->RemoveReadSocket(iSocket);
    m_pPoll->RemoveWriteSocket(iSocket);

    SocketMap::iterator itMap = m_mapSocketMap.find(iSocket);
    if (itMap != m_mapSocketMap.end())
    {
        DeleteSocketData(itMap->second);
        m_mapSocketMap.erase(itMap);
    }

#ifdef _WIN32
    closesocket(iSocket);
#else
    close(iSocket);
#endif
    return true;
}

int CNetBase::Send(const int iSocket, const char *pData, const int iLen)
{
    SocketMap::iterator itMap = m_mapSocketMap.find(iSocket);

    if (m_mapSocketMap.end() == itMap)
    {
        printf("ERROR Send|ItMap is end. socket:%d\n", iSocket);
        return 0;
    }

    SSocketData *pSocketData = itMap->second;
    if (NULL == pSocketData)
    {
        printf("ERROR Send|ItMap->second is NULL. socket:%d\n", iSocket);
        return 0;
    }

    if (pData != NULL && iLen >= 0)
    {
        //获取空间
        SBufferNode *pCurBufferNode = NULL;

        pCurBufferNode = (SBufferNode *)GetFreeData(iLen + sizeof(SBufferNode));

        if (pCurBufferNode == NULL)
        {
            printf("ERROR Send|GetFreeData is NULL. Size:%d\n", (int)(iLen + sizeof(SBufferNode)));
            return 0;
        }

        if (!SBufferNode::AddNode(pSocketData->pSendHeadNode, pCurBufferNode))
        {
            printf("ERROR Send|AddNode fail.\n");
            return 0;
        }

        pCurBufferNode->stNetPacket.uLength = iLen + sizeof(SNetPacket) - DATA_SIZE;
        pCurBufferNode->stNetPacket.uFlag = 0;
        pCurBufferNode->stNetPacket.uCheckValue = CHECK_VALUE;

        pCurBufferNode->iDealed = 0;
        pCurBufferNode->iTotal = iLen + sizeof(SNetPacket) - DATA_SIZE;
        //保存数据
        memcpy(pCurBufferNode->stNetPacket.csData, pData, iLen);
    }

    //发送数据
    int iSendTotal = 0;
    while (pSocketData->pSendHeadNode != NULL)
    {
        int iSendSize = send(pSocketData->iSocket, (char *)(&pSocketData->pSendHeadNode->stNetPacket) + pSocketData->pSendHeadNode->iDealed,
            pSocketData->pSendHeadNode->iTotal - pSocketData->pSendHeadNode->iDealed, 0);

        if (iSendSize < 0)
        {
#ifdef _WIN32
            int iRet = WSAGetLastError();
            if (iRet != WSAEWOULDBLOCK)
#else
            int iRet = errno;
            if (iRet != EINPROGRESS)
#endif
            {
                printf("ERROR Send|send size less 0.socket:%d error:%d\n", pSocketData->iSocket, iRet);
                break;
            }
        }
        else
        {
            iSendTotal += iSendSize;
            pSocketData->pSendHeadNode->iDealed += iSendSize;
        }

        //报文发送完毕，回收空间
        if (pSocketData->pSendHeadNode->iDealed >= pSocketData->pSendHeadNode->iTotal)
        {
            SBufferNode *pFree = pSocketData->pSendHeadNode;

            pSocketData->pSendHeadNode = SBufferNode::RemoveNode(pSocketData->pSendHeadNode);
            ReleaseData((char *)pFree);
        }
        else
        {
            pSocketData->iEventType |= ENM_SOCKET_EVENT_TYPE_WRITE;
            m_pPoll->AddWriteSocket(pSocketData->iSocket);
            //printf("DEBUG send not finish.Total:%d Sended:%d\n", pSocketData->pSendHeadNode->iTotal, pSocketData->pSendHeadNode->iDealed);
            break;
        }
    }
    if (iLen == 0)
    {
        return iSendTotal;
    }
    return iLen;
}

void CNetBase::Close(const int iSocket)
{
#ifdef _WIN32
    shutdown(iSocket, SD_BOTH);
#else
    shutdown(iSocket, SHUT_RDWR);
#endif
}

SSocketData * CNetBase::CreateSocketData(int iSocket, int iEventType)
{
    static int iIndex = 1;
    SSocketData *pSocketData = new SSocketData();

    if (pSocketData == NULL)
    {
        printf("ERROR CreateSocketData|new SSocketData is NULL\n");
        return NULL;
    }

    pSocketData->iID = ++iIndex;
    pSocketData->iSocket = iSocket;
    pSocketData->iEventType = iEventType;
    pSocketData->iBufferUse = 0;
    memset(pSocketData->csDataBuffer, 0, sizeof(pSocketData->csDataBuffer));

    pSocketData->pSendHeadNode = NULL;
    pSocketData->pRecvHeadNode = NULL;

    return pSocketData;
}

void CNetBase::DeleteSocketData(SSocketData *&pSocketData)
{
    if (NULL == pSocketData)
    {
        printf("ERROR DeleteSocketData|SocketData is NULL\n");
        return;
    }

    SBufferNode *pTmpBufferNode = NULL;

    while (pSocketData->pSendHeadNode != NULL)
    {
        pTmpBufferNode = pSocketData->pSendHeadNode;
        pSocketData->pSendHeadNode = SBufferNode::RemoveNode(pSocketData->pSendHeadNode);

        ReleaseData((char*)pTmpBufferNode);
    }

    while (pSocketData->pRecvHeadNode != NULL)
    {
        pTmpBufferNode = pSocketData->pRecvHeadNode;
        pSocketData->pRecvHeadNode = SBufferNode::RemoveNode(pSocketData->pRecvHeadNode);

        ReleaseData((char*)pTmpBufferNode);
    }

    delete pSocketData;
    pSocketData = NULL;
}

char * CNetBase::GetFreeData(int iSize)
{
    char * csTmp = NULL;
    if (iSize < BASE_DATA_SIZE)
    {
        csTmp = m_cBaseDataPool.Create();
    }
    else if (iSize < BASE_DATA_SIZE * 4)
    {
        csTmp = m_cBaseDataPool4.Create();
    }
    else if (iSize < BASE_DATA_SIZE * 16)
    {
        csTmp = m_cBaseDataPool16.Create();
    }
    else if (iSize < MAX_DATA_SIZE)
    {
        csTmp = m_cMaxDataPool.Create();
    }
    return csTmp;
}

void CNetBase::ReleaseData(char * csBuff)
{
    if (csBuff == NULL)
    {
        printf("ERROR ReleaseData|csBuff is NULL\n");
        return;
    }

    int iSize = *(((int *)csBuff) - 1);

    switch (iSize)
    {
    case BASE_DATA_SIZE:
        m_cBaseDataPool.Release(csBuff);
        break;
    case BASE_DATA_SIZE * 4:
        m_cBaseDataPool4.Release(csBuff);
        break;
    case BASE_DATA_SIZE * 16:
        m_cBaseDataPool16.Release(csBuff);
        break;
    case MAX_DATA_SIZE:
        m_cMaxDataPool.Release(csBuff);
        break;
    default:
        break;
    }
}
